package com.lmx.persistence.service;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.persistence.Query;

import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.springframework.stereotype.Service;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.lmx.common.constants.CommonConstants;
import com.lmx.common.util.CommonUtil;
import com.lmx.persistence.flow.enums.EmployeeLeaveEnum;
import com.lmx.persistence.service.common.BaseCrudServiceImpl;
import com.lmx.repoDomain.exception.BusinessException;
import com.lmx.repoDomain.tmodel.EmployeeLeaveFlow;

/**
 * 员工请假service实现
 *
 * @author ytche
 * @date 2017年7月12日
 *
 */
@Service(value = "employeeLeaveFlowService")
public class EmployeeLeaveFlowServiceImpl extends
		BaseCrudServiceImpl<EmployeeLeaveFlow> implements
		EmployeeLeaveFlowService {
	@Override
	public EmployeeLeaveFlow create(EmployeeLeaveFlow employeeLeaveFlow) {
		employeeLeaveFlow.setApplyTime((int) (new Date().getTime() / 1000));
		if (employeeLeaveFlow.getFlowStatus() == null) {
			employeeLeaveFlow.setFlowStatus(EmployeeLeaveEnum.APPLY.getValue());
		}
		return super.create(employeeLeaveFlow);
	}

	@Override
	public EmployeeLeaveFlow update(EmployeeLeaveFlow employeeLeaveFlow) {
		EmployeeLeaveFlow oldData = super.findOne(employeeLeaveFlow.getId());
		boolean updateInfo = oldData.getFlowStatus().equals(
				employeeLeaveFlow.getFlowStatus());
		boolean flowPassed = (oldData.getFlowStatus().equals(
				EmployeeLeaveEnum.PASS_YES.getValue()) || oldData
				.getFlowStatus().equals(EmployeeLeaveEnum.END.getValue()));
		if (updateInfo && flowPassed) {
			throw new BusinessException("",
					CommonConstants.EMPLOYEE_LEAVE_ERROR.FLOW_PASSED.lable(),
					"");
		}
		return super.update(employeeLeaveFlow);
	}

	@Override
	public List<EmployeeLeaveFlow> recordLeaveStatus(Map<String, String> filter) {
		if (!(filter.containsKey("startTime") || filter.containsKey("endTime"))) {
			return null;
		}
		Integer startTime = StringUtils.isBlank(filter.get("startTime")) ? 0
				: new Integer(filter.get("startTime"));
		Integer endTime = StringUtils.isBlank(filter.get("endTime")) ? 0
				: new Integer(filter.get("endTime"));
		List<EmployeeLeaveFlow> flows = this.findCusomerInLeave(filter);
		if (flows == null || flows.size() < 1) {
			return flows;
		}
		// 计算请假日期
		for (EmployeeLeaveFlow employeeLeaveFlow : flows) {
			// startTime取较大值,endTime取较小值
			Set<Integer> leaveDays = Sets.newHashSet();
			Integer recordStartTime = startTime > employeeLeaveFlow
					.getExpectStartTime() ? startTime : employeeLeaveFlow
					.getExpectStartTime();
			Integer recordEndTime = employeeLeaveFlow.getRealEndTime() == null
					|| employeeLeaveFlow.getRealEndTime() > endTime ? endTime
					: employeeLeaveFlow.getRealEndTime();
			recordStartTime = CommonUtil.getDayBegin(recordStartTime);
			recordEndTime = CommonUtil.getDayBegin(recordEndTime) + 3600 * 24;
			for (; recordStartTime < recordEndTime; recordStartTime = recordStartTime + 3600 * 24) {
				Integer day = new DateTime(recordStartTime.longValue() * 1000)
						.getDayOfWeek();
				// jodaTime的周日为7 转换为0
				leaveDays.add(day.equals(7) ? 0 : day);
			}
			employeeLeaveFlow.setLeaveDay(leaveDays);
		}
		// 处理重复数据
		Map<Long, EmployeeLeaveFlow> flowMap = Maps.newHashMap();
		for (EmployeeLeaveFlow employeeLeaveFlow : flows) {
			Long employeeId = employeeLeaveFlow.getApplicant().getId();
			if (flowMap.containsKey(employeeId)) {
				EmployeeLeaveFlow flow = flowMap.get(employeeId);
				flow.getLeaveDay().addAll(employeeLeaveFlow.getLeaveDay());
			} else {
				flowMap.put(employeeId, employeeLeaveFlow);
			}
		}
		flowMap.values().forEach(
				p -> p.setLeaveDayStr(StringUtils.join(p.getLeaveDay(), ",")));
		return Lists.newArrayList(flowMap.values());
	}

	/**
	 * 获取某个时间段内先关员工的请假状况
	 *
	 * @author ytche
	 * @return
	 * @date 2017年8月3日 上午11:04:58
	 */
	private List<EmployeeLeaveFlow> findCusomerInLeave(
			Map<String, String> filter) {
		String staffIds = filter.get("staffIds");
		if (StringUtils.isBlank(staffIds)) {
			return null;
		}
		List<Long> staffIdList = Lists.newArrayList();
		for (String staffId : staffIds.split(",")) {
			staffIdList.add(new Long(staffId));
		}

		String startTimeStr = filter.get("startTime");
		String endTimeStr = filter.get("endTime");
		Integer startTime = null;
		Integer endTime = null;
		String queryHql = "from EmployeeLeaveFlow as e where e.delStatus=0 and (e.flowStatus=1 or  e.flowStatus=99) and e.applicant.id "
				+ " in(:staffIds)";
		if (StringUtils.isNotBlank(startTimeStr)) {
			startTime = new Integer(startTimeStr);
			queryHql += " and (realEndTime >= :startTime or realEndTime is null ) ";
		}
		if (StringUtils.isNotBlank(endTimeStr)) {
			endTime = new Integer(endTimeStr);
			queryHql += " and expectStartTime <= :endTime ";
		}
		Query query = super.em.createQuery(queryHql).setParameter("staffIds",
				staffIdList);
		if (StringUtils.isNotBlank(startTimeStr)) {
			query.setParameter("startTime", startTime);
		}
		if (StringUtils.isNotBlank(endTimeStr)) {
			query.setParameter("endTime", endTime);
		}
		return query.getResultList();
	}
}
